package com.ruoyi.api.yh.comm;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.ruoyi.api.yh.version.ApiVersion;
import com.ruoyi.common.config.ApiConfig;
import com.ruoyi.common.config.WxConfig;
import com.ruoyi.common.constant.RedisConstant;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.BeanValidators;
import com.ruoyi.common.utils.PhoneFormatCheckUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.yh.api.R;
import com.ruoyi.common.yh.api.WeixinInit;
import com.ruoyi.common.yh.api.dtovo.comm.*;
import com.ruoyi.framework.web.service.api.ApiLoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Date;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 登入
 *
 * @author cmm
 */
@ApiSupport(order = 1)
@Api(tags="登入管理")
@RestController
@ApiVersion(1)
@RequestMapping("/{version}/app-api/login")
public class LoginController extends BaseController {

    @Autowired
    private Validator validator;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ApiLoginService apiLoginService;
    @Autowired
    private ApiConfig apiConfig;

    /**
     * openIdtoken有效性，减少获取openId
     *
     * @param
     * @return 结果
     */
    @ApiOperationSupport(author = "chenmingming",order = 2)
    @ApiOperation("检测临时token的有效性")
    @ResponseBody
    @GetMapping(value = "/checkopenIdtoken")
    public R<Boolean> checkopenIdtoken(@RequestParam String openIdtoken)
    {
        if(StringUtils.isEmpty(openIdtoken)){
            return  R.fail("为空");
        }
        String   openid= redisCache.getCacheObject(RedisConstant.API_LOGIN_USER_OPENID_TOKEN+"_"+openIdtoken);

        if(StringUtils.isNotEmpty(openid)){
            return  R.ok(true);
        }
        return  R.ok(false);
    }
    /**
     * 登录方法
     *
     * @param
     * @return 结果
     */
    @ApiOperationSupport(author = "chenmingming",order = 2)
    @ApiOperation("小程序微信登录")
    @ResponseBody
    @PostMapping(value = "/wx")
    public R<LoginVO> loginWx(@RequestBody WeixinLoginDTO weixinLoginDTO)
    {
        Set<ConstraintViolation<WeixinLoginDTO>> failures = validator.validate(weixinLoginDTO);
        if (!failures.isEmpty()) {
            return R.fail(JSONArray.toJSONString(BeanValidators.extractPropertyAndMessage(failures)));
        }
        LoginVO loginVO =new LoginVO();
        final WxMaService wxService = WeixinInit.getMaService(WxConfig.lsAppId);
        SysUser user=null;

        WxMaJscode2SessionResult session = null;
        try {
            session = wxService.getUserService().getSessionInfo(weixinLoginDTO.getCode());
            String openid=session.getOpenid();
            if(StringUtils.isNotEmpty(openid)){
                SysUser businesTUser=apiLoginService.selectBusinesTUserByPfOpenId(openid);
                /**
                 * @Author chenmingming
                 * @Description //TODO 获取
                 * @Date 20:19 2021/2/22
                 * @Param [weixinLoginDTO]
                 * @return com.ruoyi.common.lvlv.api.R<com.ruoyi.common.lvlv.api.vodto.comm.LoginVO>
                 **/

                if(null!=businesTUser&&businesTUser.getUserType()!=null&&businesTUser.getUserType().equals("02")){

                    if(businesTUser.getStatus()!=null){
                        if(businesTUser.getStatus().equals("1")){
                            loginVO.setStatus("-1");
                            return R.ok(loginVO,"用户被禁止");
                        }
                    }
                    String token = UUID.randomUUID().toString();//token
                    redisCache.setCacheObject(RedisConstant.API_LOGIN_USER_TOKEN+"_"+token,businesTUser,apiConfig.getTokenExpireTime(), TimeUnit.DAYS);
                    loginVO.setToken(token);
                    loginVO.setStatus("0");
                    String tokenOld= redisCache.getCacheObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName());
                    if(StringUtils.isNotEmpty(tokenOld)){//剔除旧的
                        redisCache.deleteObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName());
                        redisCache.deleteObject(RedisConstant.API_LOGIN_USER_TOKEN+"_"+tokenOld);
                    }
                    redisCache.setCacheObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName(),token);//存储手机号_token
                    return R.ok(loginVO,"登入成功");
                }else{
                    String tokenOpenid = UUID.randomUUID().toString();//临时存储openid
                    String temopen =redisCache.getCacheObject(RedisConstant.API_LOGIN_USER_TOKENOPENIDOPENI+"_"+openid);
                    if(temopen==null||StringUtils.isEmpty(temopen)){

                    }else{
                        tokenOpenid=temopen;
                    }
                    loginVO.setOpenIdtoken(tokenOpenid);
                    redisCache.setCacheObject(RedisConstant.API_LOGIN_USER_TOKENOPENIDOPENI+"_"+openid,tokenOpenid,60, TimeUnit.MINUTES);
                    redisCache.setCacheObject(RedisConstant.API_LOGIN_USER_OPENID_TOKEN+"_"+tokenOpenid,openid);
                    redisCache.setCacheObject(RedisConstant.API_LOGIN_USER_SESSIONKEY_TOKEN+"_"+tokenOpenid,session.getSessionKey(),60, TimeUnit.MINUTES);
                    loginVO.setStatus("1");
                    return R.ok(loginVO,"获取openID成功");
                }
            }else{
                throw new UsernameNotFoundException("登录用户：不存在");
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return R.fail(loginVO,"登入失败");
    }
    /**
     * 获取验证码
     *
     * @param
     * @return
     */
    @ApiOperationSupport(author = "chenmingming",order = 2)
    @ApiOperation("获取验证码")
    @ResponseBody
    @RequestMapping(value = "/getCode", method = RequestMethod.POST)
    public R<String> getCode(@RequestBody CodeDTO codeDTO, HttpServletRequest request)
    {
       /* if(StringUtils.isEmpty(phone)){
          return R.fail("电话号码不能为空");
        }*/
        Set<ConstraintViolation<CodeDTO>> failures = validator.validate(codeDTO);
        if (!failures.isEmpty()) {
            return R.fail(failures.iterator().next().getMessageTemplate());
        }
        if(!PhoneFormatCheckUtils.isChinaPhoneLegal(codeDTO.getPhone())){
            return R.fail("电话号码格式不对");
        }
        /*   *//**
     * 判断手机号是否已经注册
     *//*

        if (!UserConstants.NOT_UNIQUE.equals(apiLoginService.checkPhoneUnique(codeDTO.getPhone())))
        {

            if(StringUtils.isEmpty(codeDTO.getCodeType())){//单纯 登入的时候

            }


        }*/

        Object code="";
        String key="";
        if(StringUtils.isEmpty(codeDTO.getCodeType())){//登入
            code= redisCache.getCacheObject(RedisConstant.PHONE_CODE+"_"+codeDTO.getPhone());
            key=RedisConstant.PHONE_CODE;
        }else if("1".equals(codeDTO.getCodeType())){//注册
            key=RedisConstant.REGISTER_PHONE_CODE;
            code= redisCache.getCacheObject(RedisConstant.REGISTER_PHONE_CODE+"_"+codeDTO.getPhone());
        }else if("2".equals(codeDTO.getCodeType())){//修改密码
            key=RedisConstant.UPDATE_PASSWORD_CODE;
            code= redisCache.getCacheObject(RedisConstant.UPDATE_PASSWORD_CODE+"_"+codeDTO.getPhone());
        }else{
            return R.fail("无此类型验证码");
        }
        String cemsg="";
        if (code==null) {
            Object codeNum =redisCache.getCacheObject(RedisConstant.PHONE_CODE_NUM+"_"+codeDTO.getPhone());
            Integer num = null;
            if (codeNum == null) {
                num = 0;
            } else {
                num = Integer.parseInt(String.valueOf(codeNum));
            }

            if (num != null && num > 10) {
                return  R.fail("15分钟内，获取验证码超过三次");
            }
            String verifyCode = String.valueOf(new Random().nextInt(899999) + 100000);
            /**
             * 新版短信或者微信发送
             */
            /**短信发送**/
            // 发送验证码

            if("18559176792".equals(codeDTO.getPhone())||"18860112543".equals(codeDTO.getPhone())||"18695732137".equals(codeDTO.getPhone())||"18695680887".equals(codeDTO.getPhone())||"15959318147".equals(codeDTO.getPhone())) {
                verifyCode = "888888";
                cemsg="开发人员验证码：888888";
            }else {
                verifyCode = "888888";
                cemsg="开发人员验证码：888888";
               /*String msg = MsgTemplate.getNoticeMsg(MsgTemplate.MSG_CODE_SMS, verifyCode);
               SmsSendResponse smsSingleResponse = SMSUtil.sendSms(msg, codeDTO.getPhone());*/
            }

            redisCache.setCacheObject(key+"_"+codeDTO.getPhone(),verifyCode,2, TimeUnit.MINUTES);
            num = num + 1;
            redisCache.setCacheObject(RedisConstant.PHONE_CODE_NUM+"_"+codeDTO.getPhone(),num,15, TimeUnit.MINUTES);
        } else {
            // 已经发送过
            return R.fail("两分钟内已经发送过此号码");
        }
        /**
         * 发送结束
         */
        //
        return R.ok(cemsg,"验证码发送成功：模拟发送888888");
    }
    /**
     * 验证登录方法
     *
     * @param
     * @return 结果
     */
    @ApiOperationSupport(author = "chenmingming",order = 1)
    @ApiOperation("验证码登录")
    @ResponseBody
    @PostMapping
    public R<LoginVO> login(@RequestBody LoginDTO loginDTO)
    {
        Set<ConstraintViolation<LoginDTO>> failures = validator.validate(loginDTO);
        if (!failures.isEmpty()) {
            return R.fail(failures.iterator().next().getMessageTemplate());
        }
        LoginVO loginVO =new LoginVO();
        // 生成令牌
        String verifyKey = RedisConstant.PHONE_CODE+"_"+loginDTO.getPhone();
        String captcha = redisCache.getCacheObject(verifyKey);

        if(StringUtils.isEmpty(captcha)){
            return R.fail("验证码失效");
        }
        if(!captcha.equals(loginDTO.getCode())){
            return R.fail("验证码不相等");
        }
        SysUser businesTUser=apiLoginService.selectUserByUserName(loginDTO.getPhone());
        if(businesTUser==null){
            //不存在就注册账号
            businesTUser=new SysUser();
            businesTUser.setUserType("02");
            businesTUser.setUserName(loginDTO.getPhone());
            businesTUser.setStatus("0");
            businesTUser.setDelFlag("0");
            businesTUser.setNickName(loginDTO.getPhone());
            apiLoginService.registerUser(businesTUser);
        }
        String openId="";
        if(StringUtils.isNotEmpty(loginDTO.getOpenIdtoken())){
            openId =redisCache.getCacheObject(RedisConstant.API_LOGIN_USER_OPENID_TOKEN+"_"+loginDTO.getOpenIdtoken());
            businesTUser.setOpenid(openId);
        }


        if(!businesTUser.getUserType().equals("02")){
            return R.fail("该用户没权限");
        }

        if(businesTUser.getDelFlag()!=null&&"1".equals(businesTUser.getDelFlag())){
            return R.fail("用户被暂停");
        }
        apiLoginService.updateUserProfile(businesTUser);
        String token = UUID.randomUUID().toString();//token
        redisCache.setCacheObject(RedisConstant.API_LOGIN_USER_TOKEN+"_"+token,businesTUser,apiConfig.getTokenExpireTime(), TimeUnit.DAYS);
        String tokenOld= redisCache.getCacheObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName());
        if(StringUtils.isNotEmpty(tokenOld)){//剔除旧的
            redisCache.deleteObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName());
            redisCache.deleteObject(RedisConstant.API_LOGIN_USER_TOKEN+"_"+tokenOld);
        }
        redisCache.setCacheObject(RedisConstant.API_LOGIN_PHONE_TOKEN+"_"+businesTUser.getUserName(),token);//存储手机号_token
        loginVO.setToken(token);
        loginVO.setPname(businesTUser.getNickName());
        loginVO.setAvatar(businesTUser.getAvatar());
        return R.ok(loginVO,"登入成功");
    }

}
